<?php

class Oxygen {
	public static function Init(){
		if (array_key_exists('Oxygen::idSession',$_COOKIE)){
			self::$idSession = new ID($_COOKIE['Oxygen::idSession']);
		}
		else {
			self::$idSession = new ID();
			setcookie('Oxygen::idSession',self::$idSession->AsHex()/*,time()+30*60*/);
		}

		self::ClearTempFolderFromOldFiles();
		Log::Init();
		Lemma::LoadBasicDictionary();


		// init url handling
		self::$php_script = basename( $_SERVER['SCRIPT_NAME'] , '.php' );
		foreach (self::$url_pins as $key=>$value)
			self::$url_pins[$key] = Http::$GET[$key]->AsString();
		self::$idWindow = Http::$GET['window']->AsID();
		if (is_null(self::$idWindow))
			self::$idWindow = new ID();
		self::$url_pins['window'] = self::$idWindow->AsHex();



		// set the current language
		if (isset($_GET['lang'])) self::$lang = $_GET['lang'];
		$found = false;
		if (count(self::$langs)==0) self::$langs[] = 'en';
		foreach (self::$langs as $l=>$ll) if ($l == self::$lang) { $found = true;	break; }
		if (!$found) self::$lang = self::$langs[0];

		setlocale(LC_ALL,self::$lang);

		self::$actionname = Http::$GET['action']->AsString();
		if (is_null(self::$actionname)) self::$actionname = self::$default_actionname;
	}



	public static function Go(){
		// retrieve the current action and GO!
		$classname = 'Action'.self::$actionname;
		self::$action = Action::MakeGeneric($classname)->WithMode(Http::$GET['mode']->AsInteger());
		self::$content_type = self::$action->GetContentType();
		self::$charset =  self::$action->GetCharset();
		self::$content = self::$action->GetContent();

		if (Log::IsImmediateFlushingEnabled()) exit();
		header('Content-type: '.self::$action->GetContentType().'; charset='.self::$action->GetCharset());
		if (self::$action->IsAjax()) { echo Oxygen::$content; exit(); }
	}





	//
	//
	// Languages
	//
	//
	public static $langs = array();
	public static $lang = null;
	public static function AddLanguage($lang) { if (!in_array($lang,self::$langs)) { self::$langs[] = $lang; if (count(self::$langs)==1) self::$lang = $lang; } }



	//
	//
	// Charset
	//
	//
	private static $charset = 'UTF-8';
	public static function IsCharsetUnicode(){ return self::$charset == 'UTF-8'; }
	public static function SetCharset($value) { self::$charset = strtoupper($value); }
	public static function GetCharset(){ return self::$charset; }
	public static function ReadUnicode($value){
//		return self::IsCharsetUnicode() ? $value : iconv('UTF-8',self::$charset,$value);
		if (self::$charset == 'UTF-8') return $value;
		if (self::$charset == 'ISO-8859-1') return utf8_decode($value);
		throw new Exception('PHP versions before 6.0 do not support the converting of unicode to '.self::$charset.'.');
	}
	public static function ToUnicode($value){
//		return self::IsCharsetUnicode() ? $value : iconv('UTF-8',self::$charset,$value);
		if (self::$charset == 'UTF-8') return $value;
		if (self::$charset == 'ISO-8859-1') return utf8_encode($value);
		throw new Exception('PHP versions before 6.0 do not support the converting of '.self::$charset.' to unicode.');
	}
	private static $content_type = null;
	public static function SetContentType($value){ self::$content_type = $value; }
	public static function GetContentType(){
		if (is_null(self::$content_type)) {
			if (Browser::IsIE())
				self::$content_type = 'text/html';
			else
				self::$content_type = 'text/html';
				//self::$content_type = 'application/xhtml+xml';
		}
		return self::$content_type;
	}



	//
	//
	// Dictionary
	//
	//
	private static $dictionary_files = array('oxy/dictionary.xml');
	public static function GetDictionaryFiles(){ return self::$dictionary_files; }
	public static function AddDictionaryFile($filename) { if (!in_array($filename,self::$dictionary_files)) self::$dictionary_files[] = $filename; }




	//
	//
	// Temp
	//
	//
	private static $temp_folder = 'tmp';
	public static function GetTempFolder(){ return self::$temp_folder; }
	public static function SetTempFolder($value) { self::$temp_folder = $value; }
	public static function ClearTempFolderFromOldFiles(){
		$now = new DateTime();
		$now = $now->getTimestamp();
		$one_day_time = 24 * 60 * 60;
		foreach (scandir(self::$temp_folder) as $f){
			if (is_dir($f)) continue;
			$then = filemtime(self::$temp_folder.'/'.$f);
			if ($now - $then > $one_day_time){
				try{
					unlink(self::$temp_folder.'/'.$f);
				}
				catch (Exception $ex){}
			}
		}
	}



	//
	//
	// Code loaders
	//
	//
	private static $code_folders = array('oxy/src');
	private static $test_folders = array('oxy/tst');
	public static function GetCodeFolders(){ return self::$code_folders; }
	public static function AddCodeFolder($folder) { if (!in_array($folder,self::$code_folders)) self::$code_folders[] = $folder; }
	public static function GetTestFolders(){ return self::$test_folders; }
	public static function AddTestFolder($folder) { if (!in_array($folder,self::$test_folders)) self::$test_folders[] = $folder; }
	private static $class_files = null;
	private static $just_loaded_class_files = false;
	private static function ReloadClassFiles(){
		Scope::$APPLICATION['Oxygen::ClassFiles'] = null;
		self::LoadClassFiles();
	}
	private static function LoadClassFiles(){
		self::$class_files = Scope::$APPLICATION['Oxygen::ClassFiles'];
		if (is_null(self::$class_files)) {
			self::$class_files = array();
			foreach (self::$code_folders as $folder)
				self::LoadClassFilesRecursively($folder);
			Scope::$APPLICATION['Oxygen::ClassFiles'] = self::$class_files;
			self::$just_loaded_class_files = true;
		}
	}
	private static function LoadClassFilesRecursively($folder){
		foreach (scandir($folder) as $x) if ($x!='.'&&$x!='..') {
			$ff = $folder.'/'.$x;
			if (is_dir($ff))
				self::LoadClassFilesRecursively($folder.'/'.$x);
			else {
				$l = strlen($x);
				if ($l > 4) {
					$ext = substr($x,$l-4);
					if ($ext = '.php') {
						self::$class_files[basename($x,$ext)] = $ff;
					}
				}
			}
		}
	}
	public static function FindClassFile($class){
		self::LoadClassFiles();
		$r = isset(self::$class_files[$class]) ? self::$class_files[$class] : null;
		if (!self::$just_loaded_class_files) {
			if (is_null($r))
				self::ReloadClassFiles();
			elseif (!file_exists($r))
				self::ReloadClassFiles();
			$r = isset(self::$class_files[$class]) ? self::$class_files[$class] : null;
		}
		return $r;
	}

















	//
	//
	// Http context
	//
	//
	private static $php_script;
	private static $idSession;
	private static $idWindow;
	private static $url_pins = array('action'=>null,'lang'=>null,'window'=>null);
	public static function AddUrlPin($key) { self::$url_pins[$key] = null; }
	public static function GetUrlPin($key) { return self::$url_pins[$key]; }
	public static function MakeHref(){ $a = func_get_args(); return self::MakeHrefX($a); }
	public static function MakeHrefX($params){
		$z = count($params);
		$url_args = array();
		if ($z%2==1) $url_args['action'] = $params[0];
		for ($i = $z%2; $i<$z; $i+=2) $url_args[$params[$i]] = $params[$i+1];
		return self::MakeHrefFromUrlArgs($url_args);
	}
	public static function MakeHrefPreservingValues(){ $a = func_get_args(); return self::MakeHrefPreservingValuesX($a); }
	public static function MakeHrefPreservingValuesX($params){
		$z = count($params);
		$url_args = array();
		foreach ($_GET as $key=>$value) $url_args[$key] = $value;
		if ($z%2==1) $url_args['action'] = $params[0];
		for ($i = $z%2; $i<$z; $i+=2) $url_args[$params[$i]] = $params[$i+1];
		return self::MakeHrefFromUrlArgs($url_args);
	}
	public static function MakeHrefFromUrlArgs($url_args){
		$a = array();
		foreach (self::$url_pins as $key=>$value) $a[$key] = $value;
		foreach ($url_args as $key=>$value) $a[$key] = $value;
		$s = '';
		foreach ($a as $key=>$value) {
			if (is_null($value)) continue;
			$s .= $s == '' ? '?' : '&';
			$s .= $key .'='. new Url( $value );
		}
		return self::$php_script.'.php' . $s;
	}

	public static function IsPostback(){
		return strtolower($_SERVER['REQUEST_METHOD'])=='post';
	}

	public static function Redirect(Action $action) {
		while (ob_get_level()>0) ob_end_clean();
		echo Js::BEGIN."location.href=".new Js($action->GetHref()).";".Js::END;
		exit();
	}
	public static function RedirectBack(){
		while (ob_get_level()>0) ob_end_clean();
		echo Js::BEGIN."location.href=".new Js($_SERVER['HTTP_REFERER']).";".Js::END;
		exit();
	}
	public static function Refresh(){
		while (ob_get_level()>0) ob_end_clean();
		//echo Js::BEGIN."location.href=".new Js($_SERVER['REQUEST_URI']).";".Js::END;
		//echo Js::BEGIN."location.reload();".Js::END;
		echo Js::BEGIN."location.href=location.href;".Js::END;
		exit();
	}

	public static function GetBaseHref(){
		$r = 'http' . (isset($_SERVER["HTTPS"])?'s':'') . '://' . $_SERVER["SERVER_NAME"];
		if ($_SERVER["SERVER_PORT"] != '80') $r .= ":".$_SERVER["SERVER_PORT"];
		$s = $_SERVER['SCRIPT_NAME'];
		$r .= substr($s,0,strrpos($s,'/')+1);
		return $r;
	}
















	//
	//
	// Database upgrade
	//
	//
	private static $database_upgrade_files = array('oxy/_upgrade.php');
	public static function GetDatabaseUpgradeFiles() { return self::$database_upgrade_files; }
	public static function AddDatabaseUpgradeFile($filename) { if (!in_array($filename,self::$database_upgrade_files)) self::$database_upgrade_files[] = $filename; }

	public static function UpgradeDatabase(){
		$needs_refresh = false;
		foreach (self::$database_upgrade_files as $filename){
			$needs_upgrade = true;
			$key = 'Oxygen::upgrade_time_of_'. $filename;
			$time = Scope::$DATABASE[$key];
			if (!is_null($time))
				$needs_upgrade = filemtime($filename) > $time;
			if ($needs_upgrade){
				set_time_limit(0);
				Database::ClearPatchingSystem();
				require_once($filename);
				Scope::$DATABASE[$key] = time();
				if (Database::IsPatchingSystemDirty()) $needs_refresh = true;
			}
		}
		if ($needs_refresh){
			Log::Write('Upgrade complete.<br/>Total queries: '.count(Database::GetQueries()).'.<br/><br/><br/>Please refresh.<br/><br/><br/><br/>');
			exit();
		}
	}













	//
	//
	// Content
	//
	//
	private static $actionname = null;
	private static $action = null;
	private static $content = '';
	private static $default_actionname = 'Home';
	public static function SetDefaultAction($actionname) { self::$default_actionname = $actionname; }
	public static function GetActionName(){ return self::$actionname; }
	public static function GetAction(){ return self::$action; }
	public static function GetContent() { return self::$content; }
	public static function GetSessionID(){ return self::$idSession; }
	public static function GetWindowID(){ return self::$idWindow; }
	public static function GetBody(){ return self::$content; }
	public static function GetHead(){
		ob_start();
		echo '<meta http-equiv="Content-type" content="'.Oxygen::GetContentType().';charset='.Oxygen::GetCharset().'" />';

		$new_window_id = new ID();
		echo Js::BEGIN;
		echo "if(window.name!=".new Js(self::$idWindow->AsHex())."){";
		echo "  window.name=".new Js($new_window_id).";";
		echo "  window.location.href=".new Js(self::MakeHrefPreservingValues('window',$new_window_id));
		echo "}";

		// fix for Javascript for non unicode encodings
		if (!Oxygen::IsCharsetUnicode()){
			echo "encodeURIComponent=function(s){s=escape(s);while(s.indexOf('/')>= 0)s=s.replace('/','%2F');while(s.indexOf('+')>=0)s=s.replace('+','%2B');return s;};";
			echo "decodeURIComponent=function(s){while(s.indexOf('%2B')>=0)s=s.replace('%2B','+');while(s.indexOf('%2F')>=0)s=s.replace('%2F','/');return unescape(s);};";
		}

		echo "var oxygen_encoding = ".new Js(Oxygen::GetCharset()).";";
		echo Js::END;


		echo '<script type="text/javascript" src="oxy/jsc/prototype.js"></script>';
		echo '<script type="text/javascript" src="oxy/jsc/effects.js"></script>';
		//echo '<script type="text/javascript" src="oxy/jsc/scriptaculous.js"></script>';
		echo '<script type="text/javascript" src="oxy/jsc/date.js"></script>';

		echo Js::BEGIN;
		echo "document.viewport.getWidth = function(){ return window.innerWidth ? window.innerWidth : document.documentElement.clientWidth;};";
		echo "document.viewport.getHeight = function(){ return window.innerHeight ? window.innerHeight: document.documentElement.clientHeight;};";
		echo Js::END;

		echo '<script type="text/javascript" src="oxy/jsc/oxygen.js"></script>';
		echo '<link href="oxy/css/oxygen.css" rel="stylesheet" type="text/css" />';
		echo '<link href="favicon.ico" rel="icon" type="image/x-icon" />';

		$r = ob_get_clean();
		return $r;
	}






	//
	//
	// Misc
	//
	//
	public static function Hash($that){
		return strtoupper(md5(str_rot13(md5(sha1($that)))));
	}

}




?>
